package com.transpot.service.impl.customer;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.transpot.entry.customer.*;
import com.transpot.mapper.customer.ContactMapper;
import com.transpot.mapper.customer.CustomerContactMapper;
import com.transpot.mapper.customer.CustomerMapper;
import com.transpot.service.customer.CustomerService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 客户信息类的service层实现类
 */
@Service
public class CustomerServiceImpl extends ServiceImpl<CustomerMapper, Customer> implements CustomerService {
    @Autowired
    private CustomerMapper customerMapper;
    @Autowired
    private ContactMapper contactMapper;
    @Autowired
    private CustomerContactMapper customerContactMapper;

    /**
     * 存储客户信息和联系方式信息方法
     * @param customerDTO
     */
    @Override
    public void saveCustomerInfo(CustomerDTO customerDTO) {
        //创建一个客户信息对象，用来存储DTO中的客户信息部分
        Customer customer = new Customer();
        //首先把DTO对象中相同的属性复制给customer中
        BeanUtils.copyProperties(customerDTO, customer);
        // （因为Position是一个List，获取到某一个元素的方式是get(下标)，在list中0存的是省，1是市，2是区）
        //当录入了省市区代号时
        if (customerDTO.getPosition() != null && customerDTO.getPosition().size() == 3) {
            //给客户信息对象存入省代号
            customer.setProvince(customerDTO.getPosition().get(0));
            //给客户信息对象存入市代号
            customer.setCity(customerDTO.getPosition().get(1));
            //给客户信息对象存入区代号
            customer.setRegion(customerDTO.getPosition().get(2));
        }
        //添加首次创建时间,设置为当前时间
        customer.setCreateTime(LocalDateTime.now());
        //添加首次修改时间，设置为当前
        customer.setUpdateTime(LocalDateTime.now());
        //调用CustomerMapper存储客户信息对象
        customerMapper.insert(customer);
        //获取到存储后客户对象的主键
        Integer customerId = customer.getId();
        //遍历联系方式列表存储到联系信息表中
        for (Contact contact : customerDTO.getContactData()) {
            //设置创建时间为当前
            contact.setCreateTime(LocalDateTime.now());
            //设置最后一次修改时间为当前
            contact.setUpdateTime(LocalDateTime.now());
            //调用ContactMapper存储联系方式对象
            contactMapper.insert(contact);
            //获取到存储后的联系方式的主键
            Integer contactId = contact.getId();
            //创建客户联系方式中间表对象
            CustomerContact customerContact = new CustomerContact();
            //给该对象赋值为客户主键，联系方式主键
            customerContact.setCustomerId(customerId);
            customerContact.setContactId(contactId);
            //调用中间表的mapper层，存储该对象
            customerContactMapper.insert(customerContact);
        }
    }

    /**
     * 根据用户输入条件分页查询客户信息列表的方法实现
     * @param customerSearchDTO
     * @return
     */
    @Override
    public IPage<CustomerVO> getCustomerByConditionAndPage(CustomerSearchDTO customerSearchDTO) {
        //创建客户信息表的MP的分页查询对象,参数为前端传递过来的current, size即当前从第几页开始，每页有多少条数据
        IPage<Customer> customerIPage = new Page<>(customerSearchDTO.getCurrent(), customerSearchDTO.getSize());
        //创建MP的条件查询对象
        LambdaQueryWrapper<Customer> customerLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件
        //eq()函数代表与哪个字段相同的意思，他的三个参数分别是
        //第一个参数：要比较的字段值是否为空，为空则不设置该查询条件，不为空则设置上该查询条件
        //第二个参数：要比较的字段是对象里的哪个属性
        //第三个参数：要比较的值是什么
        //该语句的含义就是，当输入的客户名，email，类型，等级，客户ID存在时，就找出同时满足输入值等于数据库中存的客户的信息。
        customerLambdaQueryWrapper.eq(StringUtils.isNotBlank(customerSearchDTO.getName()), Customer::getName, customerSearchDTO.getName())
                .eq(StringUtils.isNotBlank(customerSearchDTO.getEmail()), Customer::getEmail, customerSearchDTO.getEmail())
                .eq(StringUtils.isNotBlank(customerSearchDTO.getKind()), Customer::getKind, customerSearchDTO.getKind())
                .eq(StringUtils.isNotBlank(customerSearchDTO.getLevel()), Customer::getLevel, customerSearchDTO.getLevel())
                .eq(StringUtils.isNotBlank(customerSearchDTO.getCarNum()), Customer::getCarNum, customerSearchDTO.getCarNum());
        //调用MP分页查询方法得到结果
        customerMapper.selectPage(customerIPage, customerLambdaQueryWrapper);
        //创建一个CustomerVO的列表存储查询结果
        List<CustomerVO> customerVOList = new ArrayList<>();
        //遍历分页查询结果，得到查到的所有的客户主键
        for (Customer customer : customerIPage.getRecords()) {
            //获得当前客户的主键
            Integer customerID = customer.getId();
            //根据主键查询客户联系方式中间表
            //设置中间表条件查询对象
            LambdaQueryWrapper<CustomerContact> customerContactLambdaQueryWrapper = new LambdaQueryWrapper<>();
            //查询条件为客户主键等于customerID的信息
            customerContactLambdaQueryWrapper.eq(CustomerContact::getCustomerId, customerID);
            //获取到中间表所有等于该客户主键的记录
            List<CustomerContact> customerContactList = customerContactMapper.selectList(customerContactLambdaQueryWrapper);
            //创建一个联系方式列表用来存储查询结果
            List<Contact> contactList = new ArrayList<>();
            //遍历查询到的所有中间表记录
            for (CustomerContact customerContact : customerContactList) {
                //获得到该条记录的联系方式主键
                Integer contactID = customerContact.getContactId();
                //根据联系方式主键去查询联系方式表获得记录
                Contact contact = contactMapper.selectById(contactID);
                //把查询结果存入创建的列表汇总
                contactList.add(contact);
            }
            //构建一个CustomerVO对象拼装结果
            CustomerVO customerVO = new CustomerVO();
            //先把客户信息拼进来
            BeanUtils.copyProperties(customer, customerVO);
            //再把处理好的联系方式列表拼进来
            customerVO.setContactData(contactList);
            //再把处理好的VO放入创建好的存CustomerVO的列表中
            customerVOList.add(customerVO);
        }
        //封装新的分页查询对象
        IPage<CustomerVO> customerVOIPage = new Page<>(customerSearchDTO.getCurrent(), customerSearchDTO.getSize());
        //把处理好的新的VO列表存进来
        customerVOIPage.setRecords(customerVOList);
        //把查询的客户总条数存进来
        customerVOIPage.setTotal(customerIPage.getTotal());
        //把结果返回
        return customerVOIPage;
    }

    /**
     * 根据客户ID删除客户信息的方法实现
     * @param id
     */
    @Override
    public void deleteCustomerById(Integer id) {
        //根据客户主键查找中间表，得到联系方式主键
        //创建中间表的条件查询对象
        LambdaQueryWrapper<CustomerContact> customerContactLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为客户信息主键相同
        customerContactLambdaQueryWrapper.eq(CustomerContact::getCustomerId, id);
        //查找中间表记录
        List<CustomerContact> customerContactList = customerContactMapper.selectList(customerContactLambdaQueryWrapper);
        //遍历中间表记录得到联系方式主键
        for (CustomerContact customerContact : customerContactList) {
            //得到联系方式主键
            Integer contactID = customerContact.getContactId();
            //根据联系方式主键删除联系方式记录
            contactMapper.deleteById(contactID);
        }
        //根据客户ID删除中间表记录
        customerContactMapper.delete(customerContactLambdaQueryWrapper);
        //根据客户ID删除客户表记录
        customerMapper.deleteById(id);
    }

    /**
     * 根据客户ID修改客户信息的方法实现
     * @param updateCustomerDTO
     */
    @Override
    public void updateCustomerById(UpdateCustomerDTO updateCustomerDTO) {
        //根据传来的客户主键查询中间表
        //创建条件查询对象
        LambdaQueryWrapper<CustomerContact> customerContactLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //设置查询条件为与客户主键相等
        customerContactLambdaQueryWrapper.eq(CustomerContact::getCustomerId, updateCustomerDTO.getId());
        //查询中间表
        List<CustomerContact> customerContactList = customerContactMapper.selectList(customerContactLambdaQueryWrapper);
        //遍历查询到的中间表信息
        for (CustomerContact customerContact : customerContactList) {
            //获得联系方式的主键
            Integer contactID = customerContact.getContactId();
            //调用删除方法删除该联系方式
            contactMapper.deleteById(contactID);
        }
        //删除中间表信息
        customerContactMapper.delete(customerContactLambdaQueryWrapper);
        //删除客户表信息
        customerMapper.deleteById(updateCustomerDTO.getId());
        //创建新的客户信息对象来处理新的客户信息
        Customer customer = new Customer();
        //把不需要处理的信息先赋值进去
        BeanUtils.copyProperties(updateCustomerDTO, customer);
        //修改最后一次修改时间
        customer.setUpdateTime(LocalDateTime.now());
        //把省市区编号拿出来存入对象
        //当录入了省市区代号时
        if (updateCustomerDTO.getPosition() != null && updateCustomerDTO.getPosition().size() == 3) {
            //给客户信息对象存入省代号
            customer.setProvince(updateCustomerDTO.getPosition().get(0));
            //给客户信息对象存入市代号
            customer.setCity(updateCustomerDTO.getPosition().get(1));
            //给客户信息对象存入区代号
            customer.setRegion(updateCustomerDTO.getPosition().get(2));
        }
        //把处理好的客户信息存入数据库
        customerMapper.insert(customer);
        //把修改过的客户的联系方式存入数据库
        for (Contact contact : updateCustomerDTO.getContactData()) {
            //如果联系方式是新增的，那么创建时间和修改时间就不存在，需要添加
            if (contact.getCreateTime() == null) {
                contact.setCreateTime(LocalDateTime.now());
            }
            if (contact.getUpdateTime() == null) {
                contact.setUpdateTime(LocalDateTime.now());
            }
            //把联系方式对象存入数据库
            contactMapper.insert(contact);
            //创建中间表对象
            CustomerContact customerContact = new CustomerContact();
            //设置联系方式主键
            customerContact.setContactId(contact.getId());
            //设置客户主键
            customerContact.setCustomerId(customer.getId());
            //把中间表对象存入数据库
            customerContactMapper.insert(customerContact);
        }
    }
}
